/*
 * // +-------------------------------------------------------------------------------------------------
 * // |                 有你就好 [ 有节骨乃坚，无心品自端 ]     <http://encoding.wang>
 * // +-------------------------------------------------------------------------------------------------
 * // |                             独在异乡为异客         每逢佳节倍思亲
 * // +-------------------------------------------------------------------------------------------------
 * // |                 联系:   <707069100@qq.com>      <http://weibo.com/513778937>
 * // +-------------------------------------------------------------------------------------------------
 */

// -----------------------------------------------------------------------------------------------------
// +----------------------------------------------------------------------------------------------------
// |                   ErYang出品 属于小极品          共同学习    共同进步
// +----------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------


package wang.encoding.mroot.admin.common.quartz


import org.quartz.*
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import wang.encoding.mroot.common.exception.UtilException
import wang.encoding.mroot.model.entity.system.ScheduleJob
import wang.encoding.mroot.model.enums.StatusEnum
import org.quartz.TriggerKey


/**
 * Quartz Scheduler 工具类
 *
 * @author ErYang
 */
object QuartzScheduleUtil {


    /**
     * logger
     */
    private val logger: Logger = LoggerFactory.getLogger(QuartzScheduleUtil::class.java)

    /**
     * 任务组 key
     */
    private const val JOB_GROUP_KEY: String = "MROOT_GROUP_JOB"
    /**
     * 任务 key
     */
    private const val JOB_KEY: String = "MROOT_JOB"
    /**
     * 触发器组 key
     */
    private const val TRIGGER_GROUP_KEY: String = "MROOT_GROUP_TRIGGER"
    /**
     * 触发器 key
     */
    private const val TRIGGER_KEY: String = "MROOT_TRIGGER"


    /**
     * 根据 scheduler 和 scheduleJob 新增定时任务
     *
     * @param scheduler   scheduler
     * @param scheduleJob ScheduleJob
     */
    @Throws(UtilException::class)
    fun addScheduleJob(scheduler: Scheduler, scheduleJob: ScheduleJob) {
        try {

            // 构建 job 信息
            val jobDetail: JobDetail = JobBuilder.newJob(QuartzScheduleJob::class.java
            ).withIdentity(QuartzScheduleUtil.getJobKey(scheduleJob)).build()

            // 表达式调度构建器
            val scheduleBuilder: CronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.cronExpression)

            // 按新的 cronExpression 表达式构建一个新的 trigger
            val trigger: CronTrigger = TriggerBuilder.newTrigger().withIdentity(QuartzScheduleUtil.getTriggerKey()).withSchedule(scheduleBuilder).build()

            // 放入参数，运行时的方法可以获取
            jobDetail.jobDataMap["scheduleJob"] = scheduleJob

            scheduler.scheduleJob(jobDetail, trigger)

            // 暂停任务
            if (StatusEnum.NORMAL.key != scheduleJob.status) {
                QuartzScheduleUtil.pauseScheduleJob(scheduler, scheduleJob)
            }

        } catch (e: SchedulerException) {
            if (logger.isErrorEnabled) {
                logger.error(">>>>>>>>创建定时任务失败$e<<<<<<<<")
            }
        }
    }

    // -------------------------------------------------------------------------------------------------

    /**
     * 根据 scheduler 和 scheduleJob 修改定时任务
     *
     * @param scheduler   scheduler
     * @param scheduleJob ScheduleJob
     */
    @Throws(UtilException::class)
    fun editScheduleJob(scheduler: Scheduler, scheduleJob: ScheduleJob) {
        try {
            // 获取触发器
            val triggerKey: TriggerKey = QuartzScheduleUtil.getTriggerKey()

            // 表达式调度构建器
            val scheduleBuilder: CronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.cronExpression)
            // 获得 trigger
            var trigger: CronTrigger? = QuartzScheduleUtil.getCronTrigger(scheduler)
                    ?: throw UtilException(">>>>>>>>更新定时任务失败，CronTrigger为空<<<<<<<<")
            // 按新的 cronExpression 表达式重新构建 trigger
            trigger = trigger!!.triggerBuilder.withIdentity(triggerKey).withSchedule(scheduleBuilder).build()

            // 放入参数，运行时的方法可以获取
            trigger.jobDataMap["scheduleJob"] = scheduleJob

            scheduler.rescheduleJob(triggerKey, trigger)

            // 暂停任务
            if (StatusEnum.NORMAL.key != scheduleJob.status) {
                QuartzScheduleUtil.pauseScheduleJob(scheduler, scheduleJob)
            }

        } catch (e: SchedulerException) {
            if (logger.isErrorEnabled) {
                logger.error(">>>>>>>>更新定时任务失败$e<<<<<<<<")
            }
        }

    }

    // -------------------------------------------------------------------------------------------------

    /**
     * 根据 scheduler 和 scheduleJob 立即执行任务
     *
     * @param scheduler   scheduler
     * @param scheduleJob 定时任务
     */
    @Throws(UtilException::class)
    fun runScheduleJob(scheduler: Scheduler, scheduleJob: ScheduleJob) {
        try {
            //参数
            val dataMap = JobDataMap()
            dataMap["scheduleJob"] = scheduleJob
            scheduler.triggerJob(QuartzScheduleUtil.getJobKey(scheduleJob), dataMap)
        } catch (e: SchedulerException) {
            if (logger.isErrorEnabled) {
                logger.error(">>>>>>>>立即执行任务失败$e<<<<<<<<")
            }
        }

    }

    // -------------------------------------------------------------------------------------------------

    /**
     * 根据 scheduler 和 scheduleJob 暂停任务
     *
     * @param scheduler scheduler
     * @param scheduleJob ScheduleJob
     */
    @Throws(UtilException::class)
    fun pauseScheduleJob(scheduler: Scheduler, scheduleJob: ScheduleJob) {
        try {
            scheduler.pauseJob(QuartzScheduleUtil.getJobKey(scheduleJob))
        } catch (e: SchedulerException) {
            if (logger.isErrorEnabled) {
                logger.error(">>>>>>>>暂停任务任务失败$e<<<<<<<<")
            }
        }
    }

    // -------------------------------------------------------------------------------------------------

    /**
     * 根据 scheduler 和 scheduleJob 恢复任务
     *
     * @param scheduler scheduler
     * @param scheduleJob ScheduleJob
     */
    @Throws(UtilException::class)
    fun resumeScheduleJob(scheduler: Scheduler, scheduleJob: ScheduleJob) {
        try {
            scheduler.resumeJob(QuartzScheduleUtil.getJobKey(scheduleJob))
        } catch (e: SchedulerException) {
            if (logger.isErrorEnabled) {
                logger.error(">>>>>>>>恢复定时任务失败$e<<<<<<<<")
            }
        }

    }

    // -------------------------------------------------------------------------------------------------

    /**
     * 根据 scheduler 和 id 删除定时任务
     *
     * @param scheduler scheduler
     * @param scheduleJob        ScheduleJob
     */
    @Throws(UtilException::class)
    fun deleteScheduleJob(scheduler: Scheduler, scheduleJob: ScheduleJob) {
        try {
            // 停止触发器
            scheduler.pauseTrigger(QuartzScheduleUtil.getTriggerKey())
            // 移除触发器
            scheduler.unscheduleJob(QuartzScheduleUtil.getTriggerKey())
            scheduler.deleteJob(QuartzScheduleUtil.getJobKey(scheduleJob))
        } catch (e: SchedulerException) {
            if (logger.isErrorEnabled) {
                logger.error(">>>>>>>>删除定时任务失败$e<<<<<<<<")
            }
        }
    }

    // -------------------------------------------------------------------------------------------------

    /**
     * 根据 scheduler 获取表达式触发器
     *
     * @param scheduler Scheduler
     * @return CronTrigger
     */
    @Throws(UtilException::class)
    fun getCronTrigger(scheduler: Scheduler): CronTrigger? {
        var cronTrigger: CronTrigger? = null
        try {
            cronTrigger = scheduler.getTrigger(QuartzScheduleUtil.getTriggerKey()) as CronTrigger
        } catch (e: SchedulerException) {
            if (logger.isErrorEnabled) {
                logger.error(">>>>>>>>获取定时任务CronTrigger出现异常$e<<<<<<<<")
            }
        } finally {
            return cronTrigger
        }
    }

    // -------------------------------------------------------------------------------------------------

    /**
     * 根据定时任务获取触发器 JobKey
     *
     * @param scheduleJob ScheduleJob
     * @return JobKey
     */
    private fun getJobKey(scheduleJob: ScheduleJob): JobKey {
        return JobKey.jobKey(JOB_KEY + scheduleJob.id, JOB_GROUP_KEY)
    }

    // -------------------------------------------------------------------------------------------------

    /**
     * 获取触发器 TriggerKey
     *
     *
     * @return TriggerKey
     */
    private fun getTriggerKey(): TriggerKey {
        return TriggerKey.triggerKey(TRIGGER_KEY, TRIGGER_GROUP_KEY)
    }

    // -------------------------------------------------------------------------------------------------

}

// -----------------------------------------------------------------------------------------------------

// End QuartzScheduleUtil class

/* End of file QuartzScheduleUtil.kt */
/* Location: ./src/main/kotlin/wang/encoding/mroot/admin/common/quartz/QuartzScheduleUtil.kt */

// -----------------------------------------------------------------------------------------------------
// +----------------------------------------------------------------------------------------------------
// |                           ErYang出品 属于小极品  O(∩_∩)O~~   共同学习    共同进步
// +----------------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------------
